var previous = null;

function getOffsetLeft(obj) {
	var offsetLeft = obj.offsetLeft;
	var parent = obj.offsetParent;
	while (parent != null) {
		offsetLeft = offsetLeft + parent.offsetLeft;
		parent = parent.offsetParent;
	}
	return offsetLeft;
}

function getOffsetTop(obj) {
	var offsetTop = obj.offsetTop;
	var parent = obj.offsetParent;
	while (parent != null) {
		offsetTop = offsetTop + parent.offsetTop;
		parent = parent.offsetParent;
	}
	return offsetTop;
}

function getBrowserWidth() {
	var windowEdge;
	if ((document.all) && (!window.opera)) {		// Internet Explorer 5
		if ((document.compatMode) && (document.compatMode != "BackCompat")) {
			windowEdge = document.documentElement.clientWidth + document.body.scrollLeft - 15;
		} else {
			windowEdge = document.body.clientWidth + document.body.scrollLeft - 15;
		}
	} else {										// Firefox and Opera
		windowEdge = window.pageXOffset + window.innerWidth - 15;
	}
	return windowEdge;
}

function getBrowserHeight() {
	var windowEdge;
	if ((document.all) && (!window.opera)) {		// Internet Explorer 5
		if ((document.compatMode) && (document.compatMode != "BackCompat")) {
			windowEdge = document.documentElement.clientHeight + document.body.scrollTop - 15;
		} else {
			windowEdge = document.body.clientHeight + document.body.scrollTop - 15;
		}
	} else {										// Firefox and Opera
		windowEdge = window.pageYOffset + window.innerHeight - 18;
	}
	return windowEdge;
}

function clearTimeoutsOnTree(e) {
	var temp = e;
	while (temp['popupOwnerParent'] != null) {
		temp = temp['popupOwnerParent'];
	}
	while (temp != null) {
		clearTimeout(temp['popupTimeout']);
		temp = temp['popupOwnerChild'];
	}
}

function isInTree(item1, item2) {
	var temp = item1;
	while (temp['popupOwnerParent'] != null) {
		temp = temp['popupOwnerParent'];
	}
	while (temp != null) {
		if (item2 == temp) {
			return true;
		}
		temp = temp['popupOwnerChild'];
	}
	return false;
}

function menuHover() {
	if (previous != null) {
		if (!isInTree(previous, this)) {
			hide(previous.id);
		}
	}
	previous = this;

	if (this['popupMouseOver'] != '') {
		this['popupMouseOver']();
	}
	clearTimeoutsOnTree(this);
	if ((this['popupChild'] != null) && (this['popupType'] == 'hover')) {
		show(this, this['popupChild']);	
		
		var temp = this;
		var count = 0;
		while (temp != null) {
			temp = temp['popupOwnerChild'];
			count++;
			if (count == 3) break;
		}
		while (temp != null) {
			if (temp['popupHideable'] != null) temp.style.visibility = 'hidden';
			temp = temp['popupOwnerChild'];
		}
	}
}

function menuClick() {
	if (this['popupClick'] != '') {
		this['popupClick']();
	}
	clearTimeoutsOnTree(this);
	if (this['popupChild'] != null) {
		show(this, this['popupChild']);
		
		var temp = this['popupChild']['popupChild'];
		while (temp != null) {
			temp.style.visibility = 'hidden';
			temp = temp['popupChild'];
		}
	}
}

function menuHide() {
	if (this['popupMouseOut'] != '') {
		this['popupMouseOut']();
	}
	if (this['popupHideable'] != undefined) {
		this['popupTimeout'] = setTimeout('hide(\'' + this.id + '\')', 400);
	}
	if (this['popupChild'] != undefined) {
		this['popupChild']['popupTimeout'] = setTimeout('hide(\'' + this['popupChild'].id + '\')', 400);
	}
}

function show(p, c) {
	var parentX = getOffsetLeft(p);
	var parentY = getOffsetTop(p);
	var parentWidth = p.offsetWidth;
	var parentHeight = p.offsetHeight;
	
	var childX = parentX;
	var childY = parentY;
	var childWidth = c.offsetWidth;
	var childHeight = c.offsetHeight;
	if (c['popupPosition'] == 'x') {
		childX += parentWidth + 2;
		if ((childX > getBrowserWidth() / 2) && (childX + childWidth > getBrowserWidth())) {
			childX = parentX - childWidth - 2;
		}
	} else {
		childY += parentHeight + 2;
		if ((childY > getBrowserHeight() / 2) && (childY + childHeight > getBrowserHeight())) {
			childY = parentY - childHeight - 2;
		}
	}
	if (childX + childWidth > getBrowserWidth()) {
		childX = getBrowserWidth() - childWidth;
	}
	if (childY + childHeight > getBrowserHeight()) {
		childY = getBrowserHeight() - childHeight;
	}
	// TODO add functionality to handle changine directions for parent changes direction for children
	
	c.style.left = childX + 'px';
	c.style.top = childY + 'px';
	
	c.style.position = 'absolute';
	c.style.visibility = 'visible';
}

function hide(id) {
	var temp = document.getElementById(id);
	while (temp['popupOwnerParent'] != null) {
		temp = temp['popupOwnerParent'];
	}
	while (temp != null) {
		if (temp['popupHideable']) {
			temp.style.visibility = 'hidden';
		}
		temp = temp['popupOwnerChild'];
	}
}

function attachPopup(ownerId, parentId, childId, type, position) {
	// TODO add functionality for onmenushow and onmenuhide to execute user-defined functions

	var p = document.getElementById(parentId);
	var c = document.getElementById(childId);

	// Configure pre-defined events so they aren't lost
	if (p['popupClick'] == null) p['popupClick'] = p.onclick;
	if (p['popupMouseOver'] == null) p['popupMouseOver'] = p.onmouseover;
	if (p['popupMouseOut'] == null) p['popupMouseOut'] = p.onmouseout;
	if (c['popupClick'] == null) c['popupClick'] = c.onclick;
	if (c['popupMouseOver'] == null) c['popupMouseOver'] = c.onmouseover;
	if (c['popupMouseOut'] == null) c['popupMouseOut'] = c.onmouseout;
	
	if (p['popupClick'] == null) p['popupClick'] = '';
	if (p['popupMouseOver'] == null) p['popupMouseOver'] = '';
	if (p['popupMouseOut'] == null) p['popupMouseOut'] = '';
	if (c['popupClick'] == null) c['popupClick'] = '';
	if (c['popupMouseOver'] == null) c['popupMouseOver'] = '';
	if (c['popupMouseOut'] == null) c['popupMouseOut'] = '';

	// Add listeners
	if (type == 'click') {
		p.onclick = menuClick;
		p.onmouseout = menuHide;
		c.onmouseover = menuHover;
		c.onmouseout = menuHide;
	} else {
		p.onmouseover = menuHover;
		p.onmouseout = menuHide;
		c.onmouseover = menuHover;
		c.onmouseout = menuHide;
	}
	
	// Configure properties
	p['popupType'] = type;
	p['popupChild'] = c;
	c['popupParent'] = p;
	c['popupPosition'] = position;
	c['popupHideable'] = true;
	
	if (ownerId != null) {
		var owner = document.getElementById(ownerId);
		p['popupOwnerParent'] = owner;
		owner['popupOwnerChild'] = p;
	}
	p['popupOwnerChild'] = c;
	c['popupOwnerParent'] = p;
	
	c.style.position = 'absolute';
	c.style.visbility = 'hidden';
}